#
# THis file is imported by the XML template, for instrument specific
# handling.
#
# BrukerFrameBuilder is a bit confused. It started off as a trial 
# method of generating metadata for ICAT based purely on records
# from the Bruker PostgreSQL database. Subsequently it has 
# been adapted to generate metadata based on real image files
# aggregated into a collection.
# It was also modified to do this for SMART files which predate 
# the Bruker PostgreSQL approach.
# Thereafter it seems reasonable to try and extract as much 
# common/generic behaviour into a base class (DatasetBuilder)
# for re-use by other instrument datacollection strategies.
#

from config import DataFormats
from datasetBuilder import DatasetBuilder


class BrukerFrameBuilder(DatasetBuilder):
    """ The idea here is to make the garbage we extract from 
the Bruker ApexII PostgreSQL database as pallatable to the 
XML template parser as possible. """

    def __init__(self,dataFormat=DataFormats.APEX):
      super(BrukerFrameBuilder,self).__init__(dataFormat)
#      self.dataFormat = dataFormat
      self.protonums = []


    def deduceFrames(self, fileproto,protonums, operations, scans=None):
      """ 
From the Bruker PostgreSQL database:
fileproto = the BAXSdb.saint.integrate_framename field
protonums = the BAXSdb.saint.integrate_nframes field
Here we generate the datasets, the filenames, (and the metadata).
      """
      self._log.info(fileproto)
      self._log.info( protonums)
      self.parseNums(protonums)
      self.buildScanMetadataFromDatabase(operations,scans)
      res = self.parseFileTemplate(fileproto)
      return res
 

    def parseNums(self, protonums):
      if protonums=='' or protonums=='"': # empty list   
        self.protonums = []
        return
      list = protonums.split(',') 
      #self.protonums = map(list, int )
      #print list
      self.protonums = map(int, list )



    def parseFileTemplate(self, fileproto):
      if fileproto=='' or fileproto=='"': return [] # No info
      #print fileproto
      #from os.ntpath import split # for windows
      from ntpath import split # for windows
      instrument = None
      if fileproto.find('.sfrm')>0:
        # its apex
        instrument = "Apex"
      else: 
        # assume its SMART  .00n
        instrument = "SMART"
      comma = fileproto.find(',')
      lb =fileproto.find('[') 
      rb =fileproto.find(']') 
      protos = [ ]
      if comma <0 and lb<0:    # just a single scan run?
        dir, name = split(fileproto) # ntpath split
        dir = self.remapDir(dir)
        if instrument=="Apex":
            name,ext = name.split('.')
            part = name.split('_')
            if len(part)>3:
               fproto = [dir,'_'.join(part[0:-2]),'_',part[-2],'_',part[-1],'.', ext ]
            elif len(part)==3:
              fproto = [ dir, part[0],'_',part[1],'_',part[2],'.', ext ]
            else:
              raise Exception, "Unknown SAINT framename pattern (1): " + fileproto

        elif instrument=="SMART":
             part = name.split('_')
             bits = part[-1].split('.')
             if len(bits)!=2:
               raise Exception, "unknown SAINT framename pattern (2): " + fileproto
             part[-1] = bits[-2]
             part.append(bits[-1])
             if len(part)>3:
               fproto = [dir,'_'.join(part[0:-2]),'_',part[-2],'.',part[-1]]
             elif len(part)==3:
               fproto = [ dir, part[0],'_',part[-2],'.',part[-1]]
             else:
               raise Exception, "unknown SAINT framename pattern (3): " + fileproto
        else:
          raise Exception, "unknown image frame type" + fileproto

        #print fproto
        protos.append(fproto)

      elif comma >0 and lb<0:     # its a comma delimited list of scans
        scans = fileproto.split(',')
        ext = ""
        bits = []
        c = -1
        for scan in scans:
          c += 1
          if c == 0:     # first has folder path prepended
            dir, name = split(scan)  # ntpath
            dir = self.remapDir(dir)
          else:
            name = scan

          if instrument=="Apex":
             if c == 0:     # first has filename extension
               name,ext = name.split('.')
             part = name.split('_')
             if len(part)>3:
               fproto = [dir,'_'.join(part[0:-2]),'_',part[-2],'_',part[-1],'.', ext ]
             elif len(part)==3:
               fproto = [ dir, part[0],'_',part[1],'_',part[2],'.', ext ]
             else:
               raise Exception, "Unknown SAINT framename pattern (1): " + fileproto
          if instrument=="SMART":
             part = name.split('_')
             if c == 0:     # first has filename extension
               bits = part[-1].split('.')
               if len(bits)!=2:
                 raise Exception, "unknown SAINT framename pattern (2): " + fileproto
               part[-1] = bits[-2]
             part.append(bits[-1])
             if len(part)>3:
               fproto = [dir,'_'.join(part[0:-2]),'_',part[-2],'.',part[-1]]
             elif len(part)==3:
               fproto = [ dir, part[0],'_',part[-2],'.',part[-1]]
             elif len(part)==2:
               fproto = [ dir, part[0],'.',part[-1]]
             else:
               raise Exception, "unknown SAINT framename pattern (3): " + fileproto
          protos.append(fproto)
          

      elif comma <0 and lb >= 0 and rb>lb:
        # its a [a-b] template
        dir, name = split(fileproto)
        dir = self.remapDir(dir)
        ext = ""
        lb = name.find('[')
        rb = name.find(']')
        rnge = name[lb+1:rb]
        rnge = rnge.split('-')
        rnge= map(int,rnge)
        if rnge[1]>9: ten_plus=True
        else: ten_plus=False
        trailer = name[rb+1: ]
        if instrument == 'Apex': 
          pre, ext = trailer.split('.')
          part = pre.split('_')
          if len(part)!=2:
            raise Exception, "unknown SAINT framename pattern (2): " + fileproto
          if part[0]!='':
            raise Exception, "unknown SAINT framename pattern (2): " + fileproto
        elif instrument == 'SMART': 
          part = trailer.split('.')
          if len(part)!=2:
            raise Exception, "unknown SAINT framename pattern (2): " + fileproto
        for idx in range(rnge[0],rnge[1]+1): #  loop for the scans 
          if ten_plus: 
            sidx = "%02d" % idx
          else:
            sidx = "%d" % idx
          if instrument == 'Apex': 
            fproto = [ dir, name[0:lb], sidx, '_',part[1],'.',ext  ]
          elif instrument == 'SMART': 
            fproto = [ dir, name[0:lb], sidx, '.',part[1]  ]

          #print fproto
          protos.append(fproto)
   
      else: 
        raise Exception, "unknown SAINT framename pattern (4): " + fileproto

      #print protos
      return protos


    def buildScanMetadataFromDatabase(self, operators, scans):
      """ operations is a list of Bruker scan parameters 
          associated with each of the filename prototypes """
      if not operators and not scans:
        self.operations =  [] 
        #raise Exception, "Empty scan list!" 
        self._log.warning("Empty scan list!")  # no metadata ...? 
        return

      if operators and not scans:
        operations = operators
        mode = "op"
      elif scans and not operators:
        operations = scans
        mode = "scan"
      elif len(operators)> len(scans):
        self._log.warning("operation/scan table mismatch: %d %d", 
             len(operators), len(scans) )
        operations = operators
        mode = "op"
      elif len(operators)< len(scans):
        self._log.warning("operation/scan table mismatch: %d %d", 
             len(operators), len(scans) )
        operations = scans
        mode = "scan"
      elif len(operators)== len(scans):
        operations = scans
        mode = "scan"
      else:
        raise Exception, "How could this happen?" 
      


      fields = "operation_types_id, time, dx, sweep, direction, width, theta, omega, chi, phi, speed"
     
      ops = []
      # from the Bruker database operation_types table
      types = {1:"None",2:"Omega scan",3:"Phi scan",9:"Still scan",
           12:"Phi360 scan",14:"Theta/2Theta scan", 15:"Chi scan" }
      n = -1
      for op in operations:
        self._log.debug("op: %s", op)
        n += 1
        if mode == "scan":
          speed = op[5]/op[1]
        else:
          speed = op[10]/60. # deg / min -> deg /sec

        # anything in CAPITALS ddb just made up
        params = [ 
          {'name': '_diffrn_measurement.method',
                        'sval': types[op[0]],
                        'units': 'n/a'},
          {'name': '_diffrn_measurement.sample_detector_distance',
                        'nval': op[2],
                        'units': 'mm'},
          {'name': '_diffrn_scan.integration_time',
                        'nval': op[1], 
                        'units': 's'},
          {'name': '_diffrn_scan.SPEED',
                        'nval': speed,
                        'units': u'\xb0/s'},
          {'name': '_diffrn_scan.id',
                        'sval': n+1,
                        'units': 'n/a'},
#          {'name': '_diffrn_scan.frames',
#                        'nval': self.protonums[n],
#                        'units': 'n/a'},
          {'name': '_diffrn_scan.AXIS_ANGLE_RANGE',
                        'nval': op[3],
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.AXIS_ANGLE_DIRECTION',
                        'nval': op[4],
                        'units': 'n/a'},
          {'name': '_diffrn_scan.AXIS_ANGLE_INCREMENT',
                        'nval': op[5],
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.DETECTOR_AXIS_ANGLE_TWOTHETA',
                        'nval': op[6],
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.GONIOMETER_AXIS_ANGLE_OMEGA',
                        'nval': op[7],
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.GONIOMETER_AXIS_ANGLE_CHI',
                        'nval': op[8],
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.GONIOMETER_AXIS_ANGLE_PHI',
                        'nval': op[9],
                        'units': u'\xb0'},
        ]
        #params['_diffrn_scan.date_start']         '2001-11-18T03:26:42'
        #params['_diffrn_scan.date_end']           '2001-11-18T03:36:45'
        #params['_diffrn_scan.frame_id_start']      mad_L2_000
        #params['_diffrn_scan.frame_id_end']        mad_L2_200
        ops.append(params)
      self.operations = ops


    def rationaliseDatasetData(self, protolist):
      pnum = len(self.protonums)  # num of each scan
      if pnum != len(protolist):  # file protos for each scan
        raise Exception, "mismatch between SAINT framename and integrate_nframes " + fileproto

      dsets = []

      # Now we have to do a sanity check
      # Some folk do wierd things, like doubly including files 
      # in their SAINT analysis??????? What the ...?
      # first parse ...

      for i in range(0,pnum):
        set = protolist[i]
        num = self.protonums[i]
        if set[-1]=='sfrm':
          type = 'Apex'
          sfld = -3
        else:
          type = 'SMART'
          sfld = -1
        sid = int(set[sfld-2])

        siter = set[sfld]
        iter = int(siter)
        dsetname = "".join(set[1:sfld-1])
        first = iter 
        last = iter + num
        dsets.append( [dsetname, first, last] )
     
      droplist= []
      for i in range(0,pnum):   # advance loop
        iname = dsets[i][0]
        ifirst = dsets[i][1]
        ilast = dsets[i][2]
        for j in range(0,i):  # back loop over prev
          if dsets[j][0] != iname: continue  
          if dsets[j][1] > ifirst: 
             dsets[j][1] = ifirst
          if dsets[j][2] < ilast:
             dsets[j][2] = ilast
          # what about potential gaps in between ???
          # too bad so sad.
          self._log.debug("dropped  %d %s",i, dsets[i] )
          dsets[i][0] = ''
          droplist.append(i)
      # ideally we could test for file existance and cull if not.

      if len(droplist)>0:
        for drop in droplist:
          protolist[drop]= None

      return protolist




    def buildDatasetsFromAggregatedFiles(self, filesets, priordata=None, purgelist=None):
      """This method builds a datastructure that the XML template method can
      iterate over to dump whole datasets of files and parameters.

      Made an executive decision to treat each scan as a dataset 
      For each image, there should be a corresponding  \work\image.raw
      integrated intensity file. should we archive those derived files too?
      """
      self.priordata = priordata # local ref
      self.purgelist = purgelist # local ref
      # from ntpath import split # for windows
      from os.path import split # for windows
      import os.path 
      import re, types
      dsetnum_re = re.compile(r".*\D(\d+)$")  # trailing digits from 
      if isinstance(filesets, list):
         # uh oh
         self._log.info("No frame file data")
         return None
      keys = filesets.keys()
      keys.sort()
      dsets = []

      # in principle, filesets are aggregated lists of recently 
      # modified or created files - i.e. files that have changed. 
      # priordata, on the otherhand, has already been injected 
      # into ICAT. reinjecting without prior removal is not allowed
      self._log.debug("priordata %s", priordata ) 
      
      for key in keys:  # loop over file groups
        # for key = SUNDRIES and INDEXING, the split doesn't work
        # in particular,there will be no dsetnum
        dir, dsetname = split(key) # ntpath split
        filelist = filesets[key] 
        filelist.sort() # ensure ordered filelist
        dsetnum = dsetnum_re.match(key)
        if not dsetnum:
          # handle this dataset some other way???
          self._log.debug("building dset: %s", key ) 
          if key == DataFormats.INDEXING: 
             scan = "indexing"
          else:
             scan = "unknown"
          dset = {'proto':None, 'num':None, 'mach':None, 
                'dsetname':dsetname,
                'description': "additional files",
                'params':[] , 'scan':scan }
          files = []
          for file in filelist:
            dir , filename = split(file)
            self._log.debug("%s %s", dir, filename ) 
            version = "?"
            elements = [ #{'name': 'description',
                         # 'content': '' }, 
#                         {'name': 'datafile_version',
#                          'content': '1' }, 
#                         {'name': 'datafile_version_comment',
#                          'content': '' }, 
                         {'name': 'datafile_format',
                          'content': 'unknown' }, 
                         {'name': 'datafile_format_version',
                          'content': version }, 
              ]
            self.addCommonFileData(file, elements)
            file = {'dir':dir, 'name':filename, 'params': [ ],
               'elements': elements }
            # probably we need to specify file types etc 
            # and or remove ICAT unsupported/registered format types
            self.purgeCheck(file)
            files.append(file)
          dset['files'] = files
          dsets.append(dset)
             
          continue

        dsetnum = dsetnum.group(1)

        sid = int(dsetnum)  # convert string to number
        if sid <1 or sid > len(self.operations): 
          """ So iether the Apex bruker software went wrong, OR,
              more likely, this is older SMART data.
          """
          # handle this dataset some other way???
          # just as a group of files ??? TBD...
          self._log.warning("No Bruker Postgres Scan operation info for %s", key)
          # smart has fixed chi, so only omega scan is possible, mainly.
          dset = {'proto':None, 'num':None, 'mach':None, 
                'dsetname':dsetname,
                'description': "Scan frame data",
                'params':[] , 'scan':"omega scan" }#assumed. no idea what kind
          files = []
          version = None
          file0 = filelist[0]
          file1 = filelist[-1]
          meta0 = None; meta1 = None
          try:
                from fileHandlers.sfrmProcess import SFRM
                filepath = dir + "/" + file0
                f = open(filepath)
                sf = SFRM(f)
                meta0 =  sf.getMetadata()
                f.close()
                filepath = dir + "/" + file1
                f = open(filepath)
                sf = SFRM(f)
                meta1 =  sf.getMetadata()
                f.close()
          except Exception, e:
                self._log.error(e)
          if file0 and file1 and file0!= file1 and meta0 and meta1:
             version =  meta0['VERSION']
             width    = float(meta0['RANGE'])
             delta    = float(meta0['INCREME'])
             axis     = int(meta0['AXIS']) 
             distance = float(meta0['DISTANC'].split()[0]) #2 values??
             wavelen  = float(meta0['WAVELEN'].split()[0])
             time     = float(meta1['ELAPSDR'].split()[0]) #2 value ?? v13
             startang = meta0['ANGLES'].split()
             endang   = meta1['ENDING'].split()
             frames   = meta1['NUMBER']
             range    = float(endang[axis-1]) - float(startang[axis-1])
             speed    = delta /time
             types = {1:"None",2:"Omega scan",3:"Phi scan",9:"Still scan",
                 12:"Phi360 scan",14:"Theta/2Theta scan", 15:"Chi scan" }
             params = [ 
          {'name': '_diffrn_measurement.method',
                        'sval': types[axis],
                        'units': 'n/a'},
          {'name': '_diffrn_measurement.sample_detector_distance',
                        'nval': distance *10.,
                        'units': 'mm'},
          {'name': '_diffrn_scan.integration_time',
                        'nval': time, 
                        'units': 's'},
          {'name': '_diffrn_scan.SPEED',
                        'nval': speed,
                        'units': u'\xb0/s'},
          {'name': '_diffrn_scan.id',
                        'sval': sid,
                        'units': 'n/a'},
#          {'name': '_diffrn_scan.frames',
#                        'nval': self.protonums[n],
#                        'units': 'n/a'},
          {'name': '_diffrn_scan.AXIS_ANGLE_RANGE',
                        'nval': range,
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.AXIS_ANGLE_DIRECTION',
                        'nval':  -1 if delta <0.0 else +1 , 
                        'units': 'n/a'},
          {'name': '_diffrn_scan.AXIS_ANGLE_INCREMENT',
                        'nval':  delta,
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.DETECTOR_AXIS_ANGLE_TWOTHETA',
                        'nval': startang[0],
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.GONIOMETER_AXIS_ANGLE_OMEGA',
                        'nval': startang[1],
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.GONIOMETER_AXIS_ANGLE_CHI',
                        'nval': startang[2],
                        'units': u'\xb0'},
          {'name': '_diffrn_scan.GONIOMETER_AXIS_ANGLE_PHI',
                        'nval': startang[3],
                        'units': u'\xb0'},
             ]
          else:
             version = "?"
             params = { }
          

          for file in filelist:
            dir1, filename = split(file)
            filepath = dir + "/" + file
            """
            if not version:  # get version number only for first data file
              try:
                from fileHandlers.sfrmProcess import SFRM
                f = open(filepath)
                sf = SFRM(f)
                meta =  sf.getMetadata()
                f.close()
                version =  meta['VERSION']
              except Exception, e:
                print e
                version = "?"
            """
            elements = [ {'name': 'description',
                          'content': 'frame' }, 
                         {'name': 'datafile_version',
                          'content': '1' }, 
#                         {'name': 'datafile_version_comment',
#                          'content': '' }, 
                         {'name': 'datafile_format',
                          'content': 'bruker smart' }, 
                         {'name': 'datafile_format_version',
                          'content': version }, 
              ]
            self.addCommonFileData(filepath,elements)
            file = {'dir':dir, 'name':filename, 'params': [ ],
               'elements': elements }
            # probably we need to specify file types etc 
            # and or remove ICAT unsupported/registered format types
            self.purgeCheck(file)
            files.append(file)
          dset['params'].append( {'name': '_diffrn_scan.frames',
                     'nval': len(filelist),
                     'units': 'n/a'} )
          dset['params'].extend(params)
          dset['files'] = files
          dsets.append(dset)
          continue
         
        ops = self.operations[sid-1]

#        set = protolist[i]
#        if not set: continue  # rationalised from existance
#        num = self.protonums[i]
        num = len(filelist)
        set = "ppppp"
        #if set[-1]=='sfrm':
        if filelist[0].endswith('.sfrm'):
          type = 'Apex'
        else:
          type = 'SMART'

        scantype = ops[0]['sval']
      
        ops.append( {'name': '_diffrn_scan.frames',
                     'nval': len(filelist),
                     'units': 'n/a'} )
        siter = sid
        dset = {'proto':set, 'num':len(filelist), 'mach':type, 
                'dsetname':dsetname,
                'description': "Scan frame data",
                'params':ops, 'scan':scantype }
        
        self._log.debug(dsetname)
        files = []
        version = None
        for file in filelist:
          filepath = dir + "/" + file
          filename = file
          # dir,filename = split(file)
          if type == 'Apex':
             i = int(''.join(filename[-9:-5]))
          else:
             i = int(''.join(filename[-3:]))

          if not version:  # get version number only for first data file
            try:
              from fileHandlers.sfrmProcess import SFRM
              f = open(filepath)
              sf = SFRM(f)
              meta =  sf.getMetadata()
              f.close()
              version =  meta['VERSION']
            except Exception, e:
              self._log.error(e)
              version = "?"
          elements = [ {'name': 'description',
                          'content': 'frame' }, 
                         {'name': 'datafile_version',
                          'content': '1' }, 
                         {'name': 'datafile_version_comment',
                          'content': '' }, 
                         {'name': 'datafile_format',
                          'content': 'bruker sfrm' }, 
                         {'name': 'datafile_format_version',
                          'content': version }, 
              ]
          self.addCommonFileData(filepath,elements)

          file = {'dir':dir, 'name':filename, 
            'elements': elements,
            'params': [ 
              {'name': '_diffrn_scan_frame.frame_id',
                        'sval': filename, 
                        'units': 'n/a'},
              {'name': '_diffrn_scan_frame.scan_id',
                        'nval': sid,
                        'units': 'n/a'},
              {'name': '_diffrn_scan_frame.frame_number',
                        'nval': i, 
                        'units': 'n/a'},
            ],
          }

          # Maybe should add  extra params here, scan, frame id, angles 
#_diffrn_scan_frame.GONIOMETER_OMEGA  # at start of scan step
#_diffrn_scan_frame.GONIOMETER_KAPPA  # at start of scan step kappa/phi
#_diffrn_scan_frame.GONIOMETER_CHI    # at start of scan or chi/phi'
#_diffrn_scan_frame.GONIOMETER_PHI    # at start of scan step
#_diffrn_scan_frame.GONIOMETER_PHIP   # at start of scan step   phi'
#_diffrn_scan_frame.DETECTOR_TWO_THETA   # at start of scan step
#_diffrn_scan_frame.DETECTOR_DISTANCE # at start of scan 
#_diffrn_scan_frame.SCAN_TYPE         # omega or phi i.e what angle changed?
#     #  don't know about omega/2theta scans. I'm not sure if they are used?
#_diffrn_scan_frame.SCAN_END           # end angle after scan.
#                             # maybe it should just be the +/- incr/decr 
#                             # because there are two ways to get there?

          self.purgeCheck(file)
          files.append(file)
        dset['files'] = files
        dset['_diffrn_scan.frame_id_start'] = files[0]['name'] 
        dset['_diffrn_scan.frame_id_end']  = files[-1]['name']
        dsets.append(dset)

      return dsets


    def buildDatasets(self, protolist):
      """Made an executive decision to treat each scan as a dataset 
      For each image, there should be a corresponding  \work\image.raw
      integrated intensity file. should we archive those derived files too?
      """
      protolist = self.rationaliseDatasetData(protolist)

      pnum = len(self.protonums)  # num of each scan
      if pnum != len(protolist):  # file protos for each scan
        raise Exception, "mismatch between SAINT framename and integrate_nframes " + fileproto

      dsets = []
      

      for i in range(0,pnum):
        set = protolist[i]
        if not set: continue  # rationalised from existance
        num = self.protonums[i]
        if set[-1]=='sfrm':
          type = 'Apex'
          sfld = -3
        else:
          type = 'SMART'
          sfld = -1
        sid = int(set[sfld-2])
        self._log.debug("%s %d", sid, len(self.operations) )
        if sid>0 and sid<=len(self.operations): # apparently the database is screwed up sometimes.
          ops = self.operations[sid-1]
          scantype = ops[0]['sval']
        else:
          scantype = 'unknown'
          ops = []

        ops.append( {'name': '_diffrn_scan.frames',
                     'nval': num,
                     'units': 'n/a'} )
        siter = set[sfld]
        iter = int(siter)
        lit = len(siter)
        dset = {'proto':set, 'num':num, 'mach':type, 
                'dsetname':"".join(set[1:sfld-1]),
                'params':ops, 'scan':scantype }
        
        #for key in ops.keys():
        #  dset[key] = ops[key]  # copy 
        files = []
        format = "%%0%dd" % lit
        for idx in range(iter,iter+num):
          dir = set[0] 
          sequ = format % idx
          new =  set[1:]
          new[sfld] = sequ
          filename =''.join(new)
          file = {'dir':dir, 'name':filename, 'params': 
            [ {'name': '_diffrn_scan_frame.frame_id',
                        'sval': filename, 
                        'units': 'n/a'},
              {'name': '_diffrn_scan_frame.scan_id',
                        'nval': i, 
                        'units': 'n/a'},
              {'name': '_diffrn_scan_frame.frame_number',
                        'nval': idx, 
                        'units': 'n/a'},
            ]
          }

          # Maybe should add  extra params here, scan, frame id, angles 
#_diffrn_scan_frame.GONIOMETER_OMEGA  # at start of scan step
#_diffrn_scan_frame.GONIOMETER_KAPPA  # at start of scan step kappa/phi
#_diffrn_scan_frame.GONIOMETER_CHI    # at start of scan or chi/phi'
#_diffrn_scan_frame.GONIOMETER_PHI    # at start of scan step
#_diffrn_scan_frame.GONIOMETER_PHIP   # at start of scan step   phi'
#_diffrn_scan_frame.DETECTOR_TWO_THETA   # at start of scan step
#_diffrn_scan_frame.DETECTOR_DISTANCE # at start of scan 
#_diffrn_scan_frame.SCAN_TYPE         # omega or phi i.e what angle changed?
#     #  don't know about omega/2theta scans. I'm not sure if they are used?
#_diffrn_scan_frame.SCAN_END           # end angle after scan.
#                             # maybe it should just be the +/- incr/decr 
#                             # because there are two ways to get there?

          files.append(file)
        dset['files'] = files
        dset['_diffrn_scan.frame_id_start'] = files[0]['name'] 
        dset['_diffrn_scan.frame_id_end']  = files[-1]['name']
        dsets.append(dset)
              
      return dsets


def getSamples(dbcnx):
    try:
      res = dbcnx.query("SELECT samples_id, sample_name, revision, when_created FROM samples ORDER by samples_id")
    except DBConnectSQLSyntaxException, msg:
            print "Select from samples failed\n%s" % msg,
            sys.exit()
    except DBConnectSQLResultException, msg:
            print "Select from samples failed\n%s" % msg,
            sys.exit()
    samples = []
    for i in range(res.ntuples):
        samples.append([])
        for j in range(res.nfields):
                samples[i].append(res.getvalue(i, j))
                try:
                    sys.stdout.write('%-15s' % res.getvalue(i, j))
                except:
                    print res.getvalue(i, j)
        print
    res.clear()
    return samples


def getSaint(dbcnx):
    try:
      res = dbcnx.query("SELECT samples_id, revision, integrate_nframes, integrate_framename FROM saint ORDER by samples_id")
    except DBConnectSQLSyntaxException, msg:
            print "Select from samples failed\n%s" % msg,
            sys.exit()
    except DBConnectSQLResultException, msg:
            print "Select from samples failed\n%s" % msg,
            sys.exit()
    frames = []
    for i in range(res.ntuples):
        frames.append([])
        for j in range(res.nfields):
                frames[i].append(res.getvalue(i, j))
                try:
                    sys.stdout.write('%-15s' % res.getvalue(i, j))
                except:
                    print res.getvalue(i, j)
        print
    res.clear()
    return frames


def getOperations(dbcnx, SAMPLEID,REVISION):
    try:
      res = dbcnx.query("SELECT operation_types_id, time, dx, sweep, direction, width, theta, omega, chi, phi, speed  FROM operations WHERE samples_id='%(SAMPLEID)s' AND active='t' AND revision='%(REVISION)s' AND (operation_types_id=2  OR operation_types_id=3)" % {'SAMPLEID':SAMPLEID, 'REVISION':REVISION })
    except DBConnectSQLSyntaxException, msg:
            print "Select from operations failed\n%s" % msg,
            sys.exit()
    except DBConnectSQLResultException, msg:
            print "Select from operations failed\n%s" % msg,
            sys.exit()
    operations = []
    for i in range(res.ntuples):
        operations.append([])
        for j in range(res.nfields):
                operations[i].append(res.getvalue(i, j))
                #try:
                #    sys.stdout.write('%-15s' % res.getvalue(i, j))
                #except:
                #    print res.getvalue(i, j)
        #print
    res.clear()
    return operations


def getStrategyScans(dbcnx, SAMPLEID,REVISION):
    try:
      res = dbcnx.query("SELECT operation_types_id, time, dx, sweep, direction, width, theta, omega, chi, phi, start_angle, end_angle  FROM strategy_scans WHERE samples_id=%(SAMPLEID)d AND active='t' AND revision=%(REVISION)d AND (operation_types_id=2  OR operation_types_id=3)" % {'SAMPLEID':SAMPLEID, 'REVISION':REVISION })
    except DBConnectSQLSyntaxException, msg:
            print "Select from operations failed\n%s" % msg,
            sys.exit()
    except DBConnectSQLResultException, msg:
            print "Select from operations failed\n%s" % msg,
            sys.exit()
    operations = []
    for i in range(res.ntuples):
        operations.append([])
        for j in range(res.nfields):
                operations[i].append(res.getvalue(i, j))
                #try:
                #    sys.stdout.write('%-15s' % res.getvalue(i, j))
                #except:
                #    print res.getvalue(i, j)
        #print
    res.clear()
    return operations


if __name__ == '__main__':
    #import and possibly override, default config info
    from xmlMapping.dbConnect import *
    from mapConfig import *

    dbcnx = DBConnection(False)
    dbcnx.pqInit(DBHOST, DBPORT, DBNAME, DBUSER, DBPASS)
    dbcnx.connect()

    samples =  getSamples(dbcnx)
    frames =  getSaint(dbcnx)


    bfb = BrukerFrameBuilder()
       
    for sample in frames:
       sid = sample[0]
       if sid != 3: continue
       rev = sample[1]
       protonums = sample[2]
       fileproto = sample[3]
       fields = "operation_types_id, time, dx, sweep, direction, width, theta, omega, chi, phi, speed"
       try:
         print sid, fileproto
         #ops = getOperations(dbcnx,sid,rev)
         ops = getStrategyScans(dbcnx,sid,rev)
         print fields
         for op in ops:
           print op
         zzz = bfb.deduceFrames(fileproto,protonums, ops)
         if zzz:
           for it in zzz:
             print "   ", it
           yyy = bfb.buildDatasets(zzz)
           #print yyy
           print protonums
         else: 
           print None 

       except Exception, m:
         import traceback
         traceback.print_exc(file=sys.stdout)
         print sid, m
         
      
